using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace CVS
{
    public class Timer
    {
        private int _default = 1000;
        private Thread _timer1, _timer2;
        IRemoteServer _objServer, _objReplica, _objOwn;
        private static List<string> _serverList = new List<string>();
        private static List<string> _replicateList = new List<string>();
        private static string _address;

        public void StartTimer(string address)
        {
            _address = address;
            _timer1 = new Thread(new ThreadStart(this.TimerReplicate));
            _timer1.Start();

            _timer2 = new Thread(new ThreadStart(this.TimerServer));
            _timer2.Start();
        }

        public void StopTimer()
        {
            _timer1.Abort();
            _timer2.Abort();
        }

        public void AddReplicaToList(string address)
        {
            //If this server isn't already in the ping list, then add it
            if (!_replicateList.Contains(address))
            {
                _replicateList.Add(address);
            }
        }

        public void RemoveReplicaFromList(string address)
        {
            _replicateList.Remove(address);
        }

        private void TimerServer()
        {
            string address = ""; ;
            while (true)
            {
                Thread.Sleep(_default);

                try
                {
                    for (int i = 0; i < _replicateList.Count; i++)
                    {
                        address = _replicateList[i];
                        _objReplica = (IRemoteServer)Activator.GetObject(typeof(IRemoteServer), "tcp://" + address + "/MyRemoteServer");
                        _objReplica.Ping();
                    }
                }
                catch
                {
                    //Replica did not respond. Choose a new server to hold a replica
                    RemoveReplicaFromList(address);
                    _objOwn = (IRemoteServer)Activator.GetObject(typeof(IRemoteServer), "tcp://" + _address + "/MyRemoteServer");
                    _objOwn.UpdateNetwork(address);
                }
            }
        }

        public void AddServerToList(string address)
        {
            //If this server isn't already in the ping list, then add it
            if (!_serverList.Contains(address))
            {
                _serverList.Add(address);
            }
        }

        public void RemoveServerFromList(string address)
        {
            _serverList.Remove(address);
        }

        private void TimerReplicate()
        {
            string address = "";;
            while (true)
            {
                Thread.Sleep(_default);

                try
                {
                    for (int i = 0; i < _serverList.Count; i++)
                    {
                        address = _serverList[i];
                        _objServer = (IRemoteServer)Activator.GetObject(typeof(IRemoteServer), "tcp://" + address + "/MyRemoteServer");
                        _objServer.Ping();
                    }
                }
                catch
                {
                    //Server did not respond. Start election for new primary server
                    RemoveServerFromList(address);
                    _objOwn = (IRemoteServer)Activator.GetObject(typeof(IRemoteServer), "tcp://" + _address + "/MyRemoteServer");
                    _objOwn.ChooseNewPrimaryRepository(address);
                }
            }
        }
    }
}
